package com.sky.websocket;

import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务
 * 苍穹外卖day10_3章节对应的内容
 * 就是实现客户端与后端服务器之间的双向传输,,也就是长连接;
 * 当前这里就是当微信用户下单支付成功之后,,我们就需要给前端商家/客户端推送消息,,,这个就是这个作用;
 *      因为注入到容器中了,所以别的类可以通过@Autowired就能注入,然后调用这个类中的sendToAllClient方法来推送消息
 */

@Component
@ServerEndpoint("/ws/{sid}")    //类似学过的controller的路径,说明这个WebSocket也是根据路径进行匹配的
public class WebSocketServer {

    //存放会话对象
    private static Map<String, Session> sessionMap = new HashMap();

    /**
     * 连接建立成功调用的方法
     * 第一次握手成功之后,就建立了长连接,可以随时双方互发数据
     * 下面的sid指定的是路径参数,,就类似于以前学的id,客户端是通过这个sid来区分的
     */
    @OnOpen   //加上注解就表示这是一个回调方法
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端：" + sid + "建立连接");
        sessionMap.put(sid, session);
        //将这个会话对象,放入到map里面 
    }

    /**
     * 收到客户端消息后调用的方法
     *  下面就类似controller层的方法了,客户端发送请求,请求到我们后端controller的某个方法,然后方法就会执行
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端：" + sid + "的信息:" + message);
    }

    /**
     * 连接关闭调用的方法
     *  当客户端与我们后端的服务器连接关闭之后,,就会调用这个方法
     * @param sid
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);  //把这个对应的会话清理掉
    }

    /**
     * 群发
     *  注意:  这个方法前面就没有加上对应的注解,可以和上面对比;  那就说明这个方法需要我们主动去调,不能自动回调了
     *  作用:  这个方法就是推送消息给客户端/前端浏览器商家管理页面
     *  自己理解:  这个群发的意思,就是把所有客户端的会话对象遍历出来,因为客户端可能有多个,所以这个信息是
     *      发送给对应的所有客户端,,因为最开始存储会话的对象的时候,对应的key就是各个客户端的id,这里的叫sid
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器(我们的后端)向客户端(浏览器)发送消息
                session.getBasicRemote().sendText(message);   
                    //websocket是双向通信,所以这里后端也可以直接向前端发对应的消息
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
